Skip to content

refactor: route all markdown parsing through mdq() (plan 022)#93

Merged
DenysKuchma merged 3 commits into
mainfrom
refactor/mdq-compliance
Jul 16, 2026
Merged

refactor: route all markdown parsing through mdq() (plan 022)#93
DenysKuchma merged 3 commits into
mainfrom
refactor/mdq-compliance

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

Plan 022 — Route all markdown manipulation through mdq()

The project rule (CLAUDE.md, twice) is absolute: all markdown manipulation goes through mdq() — never regex, .includes(), or line-splitting. This fixes 8 violations, including 4 hand-rolled marked.lexer walks that re-implemented mdq's own section logic with subtly different semantics.

New mdq API (additive only)

MarkdownQuery.meta()Array<{type, depth, text}> — exposes token type, heading depth, and unwrapped text. This is the gap that forced the lexer walks. 6 new unit cases in markdown-query.test.ts.

Migrated

  • researcher.ts ## Summary regex + researcher/parser.ts .includes('Extended Research') → mdq queries.
  • planner.ts cleanExperienceFlows + table swap → positional .replace() with re-query-after-each-mutation (offsets go stale after a replace). Removed all String.replace(section.text(), …) and /^---/gm.
  • experience-tracker.ts: whole-section truncation (never cuts mid-code-fence), writeAction/writeFlow dedup via mdq, and listTocHeadings/extractHeadingSection/renderAsHowTo rebuilt on meta().
  • experience-compactor.ts: listSections on section2+meta(); the re-hardcoded clickXY regex → isNonReusableCode().
  • knowledge-tracker.ts firstLine → mdq().meta().
  • marked import removed from experience-tracker and experience-compactor.

Two deviations (both improvements, verified)

  1. renderAsHowTo uses startsWith via meta(), not the plan's literal h2(~"marker"). That contains-matcher would infinite-loop on a title containing the marker (## FLOW: undo FLOW: steps) and diverges from the old startsWith. The implemented version provably terminates and matches the old output (whitespace-only diff — the old code accidentally doubled blank lines).
  2. cleanExperienceFlows' > ... and N more discoveries note was dead code — the old .replace() no-op'd because the tail blockquotes were already removed from the string. The new code correctly appends it, as the plan specifies.

STOP-candidates cleared

  • Step 5 mixed-depth section indexing — verified byte-identical to the old lexer walk across all indices (h1–h4, out-of-range).
  • Step 7 clickXY → isNonReusableCode broadening — no test pins the narrow behavior; the #ember123 case yields the same final result (dropped at strip stage). All 43 compactor tests pass.

Verification

  • bun test tests/unit772 pass / 0 fail (+8 new tests; no existing assertions modified).
  • bun test tests/integration/63 pass / 0 fail.
  • bun run lint → clean; tsc total neutral (639 = 639).
  • grep marked in both files → empty; ## Summary regex gone; meta() present.

🤖 Generated with Claude Code

Enforce the "no regex/includes/line-splitting on markdown" rule across 8
violation sites. Adds one additive accessor — MarkdownQuery.meta() returning
{type, depth, text} — which removes the need for hand-rolled marked.lexer
walks. The `marked` import is now gone from experience-tracker and
experience-compactor.

- researcher Summary regex + parser `.includes('Extended Research')` -> mdq queries
- planner cleanExperienceFlows + table swap -> positional replaces with
  re-query-after-each-mutation (no more String.replace on section raw text /
  /^---/gm regex)
- experience-tracker: whole-section truncation (never cuts mid-fence),
  writeAction/writeFlow dedup via mdq, listTocHeadings/extractHeadingSection/
  renderAsHowTo rebuilt on meta()
- experience-compactor: listSections on mdq; clickXY regex -> isNonReusableCode
- knowledge-tracker firstLine via mdq().meta()

Deviations (both improvements, verified): renderAsHowTo matches with startsWith
via meta() (the plan's contains-matcher would infinite-loop on titles
containing the marker); planner's "and N more discoveries" note-append was
previously dead code (no-op after the tail blockquotes were removed) and now
correctly appends. Step 5 verified byte-identical to the old lexer walk;
Step 7's clickXY->isNonReusableCode broadening pinned by no test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

Explorbot Self-Regression

Commit dbd5c27 · run

Scenario Result Attempts Duration
basic (native) PASS 1/3 10m
experience: control OK — failed as expected 1/1 3m
experience: seeded PASS 1/3 1m

Attempt details

  • basic (native) attempt 1 — PASS: login evidence: PASS (post-login plan=true, post-login research=true); research: PASS (files=5, wellFormed=true, keywords=7/3); scenarios: PASS (tests=7/5, features=4/3); tests passed: PASS (5 passed, 0 failed (reporter: 5 passed, 0 failed))
  • experience: control attempt 1 — PASS: control: OK — failed as expected (0 passed, 1 failed)
  • experience: seeded attempt 1 — PASS: seeded: PASS (1 passed, 0 failed)

Session analysis — basic (native):

Session Analysis

The issues list feature was explored across 5 test scenarios covering creation, search, filtering by status and label, and detail navigation. All core flows work correctly. The standout observation is that two tests required multiple click attempts to succeed, suggesting automation reliability concerns rather than product defects.

Coverage

  • Pages: /issues, /issues/7
  • Features: Issue creation, keyword search, status filtering, label filtering, detail navigation

What works

  • Issue creationET-1 Create new issue and verify it appears in list
  • Keyword searchET-2 Search for existing issue by keyword
  • Status filteringET-3 Filter issues by status
  • Label filteringET-4 Filter issues by label
  • Detail navigationET-5 Navigate from list to issue detail

Execution Issues

  • ET-1 — initial click on Create button failed, retry succeeded
  • ET-5 — initial click on issue link failed, multiple retries succeeded

Comment thread src/ai/planner.ts Outdated
for (const bq of blockquotes.slice(10)) {
result = result.replace(bq.text(), '');
const trimmedTitles = new Set<string>();
while (true) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not do while true!!!!
seems like we should simplify it

Comment thread src/experience-tracker.ts Outdated
{ marker: 'FLOW:', suffix: 'multi-step' },
{ marker: 'ACTION:', suffix: 'single-step' },
]) {
while (true) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model keeps doing while(true)
i think we can move this iterator to the mdq

like

mdq(result).forEach('h2', ...)

@DavertMik DavertMik left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea is good but while true must be avoided
it doesn't simplify things!

DavertMik added a commit that referenced this pull request Jul 15, 2026
Only the items in files untouched by the other open refactor PRs, so this
does not conflict with them:
- fisherman-tools: `value === null || value === undefined` -> `value == null`
  (0/''/false are valid field values, so not `!value`)
- quartermaster: move the 4 interfaces to end of file; outputPath('a11y')
  instead of join(getOutputDir(), 'a11y'); drop the existsSync guard
  (mkdirSync recursive tolerates existing) and inline ensureDirectory away.

The bulk of plan 016 (private-method reordering, type-moves, ternary and
conditional-spread cleanups across tester/tools/provider/pilot/etc.) is
DEFERRED: 016 is the run-last plan and pure-move reorderings conflict with
every open PR. It should run after #85-#93 land.

Co-authored-by: DavertMik <davert@testomat.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@DenysKuchma
DenysKuchma merged commit da7f722 into main Jul 16, 2026
3 checks passed
@DenysKuchma
DenysKuchma deleted the refactor/mdq-compliance branch July 16, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants